package com.defan.api.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.apache.http.util.TextUtils;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Stack;

/**
 * Created by 张俊强~ on 2017/10/17.
 */
public class JSONUtils {

    private static String SPACE = "   ";

    private static Stack<String> tableStack = new Stack<String>();
    private static Integer tableLevel = 0;                            //标志当前table的层级
    private static Stack<String> outputTableStack = new Stack<String>();
    private static Integer outputTableLevel = 0;                            //标志当前table的层级

    /**
     * 返回格式化JSON字符串.
     * @author 张俊强~
     *
     * @param json 未格式化的JSON字符串.
     * @return 格式化的JSON字符串 .
     *
     */
    public static String formatJson(String json) {
        StringBuffer result = new StringBuffer();

        int length = json.length();
        int number = 0;
        char key = 0;
        //遍历输入字符串。
        for (int i = 0; i < length; i++) {
            //1、获取当前字符。
            key = json.charAt(i);
            //2、如果当前字符是前方括号、前花括号做如下处理：
            if ((key == '[') || (key == '{')) {
                //（1）打印：当前字符。
                result.append(key);
                //（2）前方括号、前花括号，的后面必须换行。打印：换行。
                result.append('\n');
                //（3）每出现一次前方括号、前花括号；缩进次数增加一次。打印：新行缩进。
                number++;
                result.append(indent(number));
                //（4）进行下一次循环。
                continue;
            }

            //3、如果当前字符是后方括号、后花括号做如下处理：
            if ((key == ']') || (key == '}')) {
                //（1）后方括号、后花括号，的前面必须换行。打印：换行。
                result.append('\n');
                //（2）每出现一次后方括号、后花括号；缩进次数减少一次。打印：缩进。
                number--;
                result.append(indent(number));
                //（3）打印：当前字符。
                result.append(key);
                //（4）如果当前字符后面还有字符，并且字符不为“，”，打印：换行。
                if (((i + 1) < length) && (json.charAt(i + 1) != ',')) {
                    result.append('\n');
                }
                //（5）继续下一次循环。
                continue;
            }

            //4、如果当前字符是逗号。逗号后面换行，并缩进，不改变缩进次数。
            if ((key == ',')) {
                result.append(key);
                result.append('\n');
                result.append(indent(number));
                continue;
            }
            //5、打印：当前字符。
            result.append(key);
        }
        return result.toString();
    }

    /**
     * 返回指定次数的缩进字符串。每一次缩进三个空格，即SPACE.
     *
     * @author 张俊强~
     * @param number 缩进次数.
     * @return 指定缩进次数的字符串.
     */
    private static String indent(int number) {
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < number; i++) {
            result.append(SPACE);
        }
        return result.toString();
    }

    /**
     * 将json转输入参数表格.
     *
     * @author 张俊强~
     * @param json 未格式化的JSON字符串.
     * @return the string
     */
    public static String formatJsonToParamTable(String json) {
        tableLevel++;
        String result = "";

        LinkedHashMap<String, String> jsonMap = JSON.parseObject(json, new TypeReference<LinkedHashMap<String, String>>() {
        });

        for (Map.Entry<String, String> entry : jsonMap.entrySet()) {

            tableStack.add("|" + entry.getKey() + "|    string   |    是   |    无   |\n");

            switch (getJSONType(entry.getValue())) {
                case MessUtils.JSON_TYPE_ARRAY:
                    JSONArray jsonArray = JSON.parseArray(entry.getValue().toString());
                    if (jsonArray.size() > 0) {
                        tableStack.pop();
                        String listPre = "";
                        for (int i = 0; i < tableLevel; i++) {
                            listPre += " -";
                        }
                        tableStack.add("|" + listPre + " " + entry.getKey() + "|    object   |    是   |    无   |\n");
                        for (int i = 0; i < jsonArray.size(); i++) {
                            formatJsonToParamTable(jsonArray.get(i).toString());
                        }
                    }
                    break;
                case MessUtils.JSON_TYPE_OBJECT:
                    formatJsonToParamTable(entry.getValue());
                    break;
                case MessUtils.JSON_TYPE_ERROR:
                    break;
                default:
                    break;
            }
        }
        tableLevel--;
        if (tableLevel == 0) {
            for (int i = 0; i < tableStack.size(); i++) {
                result += tableStack.get(i);
            }
            tableStack = new Stack<String>();
        }

        return result;
    }

    public static int getJSONType(String str) {
        if (TextUtils.isEmpty(str)) {
            return MessUtils.JSON_TYPE_ERROR;
        }

        final char[] strChar = str.substring(0, 1).toCharArray();
        final char firstChar = strChar[0];


        if (firstChar == '{') {
            return MessUtils.JSON_TYPE_OBJECT;
        } else if (firstChar == '[') {
            return MessUtils.JSON_TYPE_ARRAY;
        } else {
            return MessUtils.JSON_TYPE_ERROR;
        }
    }

    /**
     * 将json转输出结果表格.
     *
     * @author 张俊强~
     * @param json 未格式化的JSON字符串.
     * @return the string
     */
    public static String formatJsonToOutputTable(String json) {
        outputTableLevel++;
        String result = "";

        LinkedHashMap<String, String> jsonMap = JSON.parseObject(json, new TypeReference<LinkedHashMap<String, String>>() {
        });

        for (Map.Entry<String, String> entry : jsonMap.entrySet()) {

            outputTableStack.add("|" + entry.getKey() + "|    string   |    无   |\n");

            switch (getJSONType(entry.getValue())) {
                case MessUtils.JSON_TYPE_ARRAY:
                    JSONArray jsonArray = JSON.parseArray(entry.getValue().toString());
                    if (jsonArray.size() > 0) {
                        outputTableStack.pop();
                        String listPre = "";
                        for (int i = 0; i < outputTableLevel; i++) {
                            listPre += " -";
                        }
                        outputTableStack.add("|" + listPre + " " + entry.getKey() + "|    object   |    无   |\n");
                        for (int i = 0; i < 1; i++) {       //实例显示一条即可
                            formatJsonToOutputTable(jsonArray.get(i).toString());
                        }
                    }
                    break;
                case MessUtils.JSON_TYPE_OBJECT:

                    formatJsonToOutputTable(entry.getValue());
                    break;
                case MessUtils.JSON_TYPE_ERROR:
                    break;
                default:
                    break;
            }
        }
        outputTableLevel--;
        if (outputTableLevel == 0) {
            for (int i = 0; i < outputTableStack.size(); i++) {
                result += outputTableStack.get(i);
            }
            outputTableStack = new Stack<String>();
        }

        return result;
    }

    /**
     * 删除json字符串中对应的数组的数目
     *
     * @author 张俊强~
     * @param json
     * @param maxSize 保留在当前json中的数组的最大大小
     * @return
     */
    public static String simplifyJsonArrayNumber(String json, Integer maxSize) {
        LinkedHashMap<String, String> jsonMap = JSON.parseObject(json, new TypeReference<LinkedHashMap<String, String>>() {
        });
        JSONObject tempJsonObject = new JSONObject();
        for (Map.Entry<String, String> entry : jsonMap.entrySet()) {
            switch (getJSONType(entry.getValue())) {
                case MessUtils.JSON_TYPE_ARRAY:
                    JSONArray jsonArray = JSON.parseArray(entry.getValue().toString());
                    if (jsonArray.size() > 0) {
                        int size = maxSize > jsonArray.size() ? jsonArray.size() : maxSize;
                        JSONArray tempJsonArray = new JSONArray();
                        for (int i = 0; i < size; i++) {       //实例显示maxSize条即可
                            String tmp = simplifyJsonArrayNumber(jsonArray.get(i).toString(), maxSize);
                            tempJsonArray.add(JSON.parseObject(tmp));
                        }
                        tempJsonObject.put(entry.getKey(), tempJsonArray);
                    }
                    break;
                case MessUtils.JSON_TYPE_OBJECT:
                    tempJsonObject.put(entry.getKey(), JSON.parseObject(simplifyJsonArrayNumber(entry.getValue(), maxSize)));
                    break;
                case MessUtils.JSON_TYPE_ERROR:
                    tempJsonObject.put(entry.getKey(), entry.getValue());
                    break;
                default:
                    break;
            }
        }
        return tempJsonObject.toJSONString();
    }
}
